home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************
- *
- * Editor.c Defines types and code for generic text editor
- *
- * Modification History:
- * 18/2/92 created from scratch.
- *
- *
- *
- *************************************************************************************/
- #include "EditGlobalEqu.p"
-
- #include "Editor.proto.h"
-
-
- textEdHdl GetWEditRecord(WindowPtr theWindow);
- char IsEditKind(WindowPtr theWindow);
-
-
- lineHdl NewEmptyLine(int nChars)
- {
- /* allocates space for a new line record according to the number of chars required
- sets the link pointers to NIL and length to nChars */
-
- lineHdl temp;
-
- temp = (lineHdl) NewHandle(nChars+(sizeof(lineHdl)*2)+1);
- if (temp != NIL) {
- (*temp)->theLine[0] = nChars;
- (*temp)->nextLine = NIL;
- (*temp)->lastLine = NIL;
- }
- return(temp);
- }
-
-
- textEdHdl NewEditRecord(WindowPtr ownerWindow)
- {
- /* creates and returns handle to new initialised edit record, with empty list. The
- handle is also copied to the wRefCon field of the owner window. Normally called
- for you by InitEditWindow */
-
- textEdHdl temp;
- Rect tView;
- GrafPtr savePort;
-
- temp = (textEdHdl)NewHandle(sizeof(textRecord));
- if (temp != NIL && ownerWindow != NIL) {
- GetPort(&savePort);
- SetPort(ownerWindow);
- SetRect(&tView,0,0,256,10);
- TextFont(monaco);
- TextSize(9);
- TextFace(0);
- PenNormal();
- (*temp)->listHead = NIL;
- (*temp)->listTail = NIL;
- (*temp)->endSelChar = 0;
- (*temp)->curEdLin = 0;
- (*temp)->owner = ownerWindow;
- (*temp)->vScroll = NIL;
- (*temp)->hScroll = NIL;
- (*temp)->lineEditRec = NIL;
- (*temp)->hiliteLine = 0;
- (*temp)->asmFile.good = FALSE;
- SetDefaultTabs(temp);
- SetPort(savePort);
- SetWRefCon(ownerWindow,(long)temp);
- }
- return(temp);
- }
-
-
- SetDefaultTabs(textEdHdl theText)
- {
- /* clears tab record except for standard tab defaults */
-
- int i;
-
- if (theText != NIL) {
- for(i=0;i<10;(*theText)->tabs[i] = 4*i,i++);
-
- }
- }
-
-
- lineHdl GetListHead(textEdHdl theEditRec)
- {
- /* returns listHead field */
- if (theEditRec != NIL)
- return((*theEditRec)->listHead);
- }
-
- lineHdl GetListTail(textEdHdl theEditRec)
- {
- /* returns listTail field */
- if (theEditRec != NIL)
- return((*theEditRec)->listTail);
- }
-
-
- SetListHead(textEdHdl theEditRec,lineHdl theLink)
- {
- /* sets listHead field */
- if (theEditRec != NIL)
- (*theEditRec)->listHead = theLink;
- }
-
-
- SetListTail(textEdHdl theEditRec,lineHdl theLink)
- {
- /* sets listTail field */
- if (theEditRec != NIL)
- (*theEditRec)->listTail = theLink;
- }
-
-
- int GetTabBarHeight(textEdHdl theText)
- {
- /* gets value of tabheight field */
-
- if (theText != NIL)
- return((*theText)->tabHeight);
- else
- return(0);
- }
-
-
- SetTabBarHeight(textEdHdl theText,int tHeight)
- {
- /* sets value of tabheight field (0 hides the bar) */
- if (theText != NIL)
- (*theText)->tabHeight = tHeight;
- }
-
-
- PushLink(lineHdl theLink,lineHdl *listHead,lineHdl *listTail)
- {
- /* faster routine for inserting link as first item in list. Useful for building list
- from text file as list is treated as a stack */
-
- lineHdl temp;
-
- if (theLink != NIL) {
- temp = *listHead;
- (*theLink)->nextLine = temp;
- (*theLink)->lastLine = NIL;
- (*temp)->lastLine = theLink;
- if (*listHead == NIL && *listTail == NIL)
- *listTail = theLink;
-
- *listHead = theLink;
- }
- }
-
-
- ReversePushLink(lineHdl theLink,lineHdl *listHead,lineHdl *listTail)
- {
- /* as above, but pushes link onto tail of list */
- lineHdl temp;
-
- if (theLink != NIL) {
- temp = *listTail;
- (*theLink)->lastLine = temp;
- (*theLink)->nextLine = NIL;
- (*temp)->nextLine = theLink;
- if (*listHead == NIL && *listTail == NIL)
- *listHead = theLink;
-
- *listTail = theLink;
- }
- }
-
-
- lineHdl GetLinkHandle(lineHdl listHead,int linkID)
- {
- /* returns the handle of the link with the given ID, or NIL if no such link exists.
- links are numbered starting at 1 [no link zero] */
-
- lineHdl temp;
- int linkNumber = 0;
-
- while (listHead != NIL) {
- linkNumber++;
- if (linkNumber == linkID)
- return(listHead);
- listHead = (*listHead)->nextLine;
- }
- return(NIL);
- }
-
-
- lineHdl BuildLine(Ptr *srcPtr,int maxChars)
- {
- /* given a pointer to a block of text, the next line is retrieved, converted to
- AAG format, copied to a new link record who's handle is returned. The line
- length is also returned so that the source pointer can be updated. */
-
- char newLine[256],theChar;
- int noInSect,dest;
- Byte lineLength;
- lineHdl temp;
- Ptr src;
-
- dest = 1;
- src = *srcPtr;
- lineLength = 0;
- noInSect = 0;
-
- do {
- theChar = *src;
- src++;
- while (theChar>=0x20 && theChar<=0xD8 && lineLength < maxChars) {
- noInSect++;
- newLine[dest + noInSect] = theChar;
- lineLength++;
- theChar = *src;
- src++;
- }
- if (theChar == 0x09 || theChar == 0x0D || lineLength >= maxChars) {
- lineLength++;
- newLine[dest] = (char) noInSect;
- dest += noInSect +1;
- noInSect = 0;
- }
- }
- while (theChar != 0x0D && lineLength < maxChars);
- newLine[0] = lineLength;
- temp = NewEmptyLine(lineLength);
- if (temp != NIL) {
- HLock((Handle) temp);
- BlockMove(&newLine,&(*temp)->theLine,lineLength+1);
- HUnlock((Handle) temp);
- }
- *srcPtr = src;
- return(temp);
- }
-
-
- lineHdl BuildBasicLine(Ptr *srcPtr,int maxChars)
- {
- /* builds a line record without taking tabs into account */
- char newLine[256],theChar;
- Ptr src,dest;
- int charCount;
- lineHdl link;
-
- charCount = 0;
- dest = &newLine[1];
- src = *srcPtr;
-
- do {
- theChar = *src;
- if ((theChar >= 0x20 && theChar <= 0xD8) || theChar == 0x09) {
- *dest = theChar;
- dest++;
- charCount++;
- }
- src++;
- }
- while (theChar != 0x0D && charCount < maxChars);
-
- newLine[0] = charCount;
- link = NewEmptyLine(charCount);
- if (link != NIL) {
- HLock((Handle) link);
- BlockMove(&newLine,&(*link)->theLine,charCount+1);
- HUnlock((Handle) link);
- }
- *srcPtr = src;
- return(link);
- }
-
-
- TextToList(lineHdl *listTail,lineHdl *listHead,char *theText,long textLength)
- {
- /* major function to build a new list from a text array in memory. theText is a
- pointer to this array. listHead/Tail should initially be NIL (new list) */
-
- long charCount,amountToGo;
- char *srcPtr,*oldSrcPtr;
- lineHdl newLink;
-
- charCount = 0;
- srcPtr = theText;
- oldSrcPtr = theText;
-
- while (charCount < textLength) {
- amountToGo = textLength - charCount;
- newLink = BuildLine(&srcPtr,(amountToGo > 253)? 254:amountToGo);
- if (newLink != NIL)
- ReversePushLink(newLink,listHead,listTail);
- charCount += (long)srcPtr - (long)oldSrcPtr;
- oldSrcPtr = srcPtr;
- }
- }
-
-
- lineHdl GetTopLine(textEdHdl theText)
- {
- /* returns handle to the line at the top of the window */
- return(GetLinkHandle(GetListHead(theText),(*theText)->topLine));
- }
-
-
- lineHdl GetBottomLine(textEdHdl theText)
- {
- /* returns handle to the line at the bottom of the window */
- return(GetLinkHandle(GetListHead(theText),(*theText)->topLine + (*theText)->linesInWindow));
- }
-
-
- SetHiliteLine(WindowPtr theWindow,long theLine)
- {
- /* sets value of hiliteLine field in text record to value. 0 means no hilite */
-
- textEdHdl theText;
-
- theText = GetWEditRecord(theWindow);
- if (theText != NIL)
- (*theText)->hiliteLine = theLine;
-
- }
-
-
- CalcLinesToDraw(textEdHdl theText,Rect *theRect,lineHdl *top,lineHdl *bottom,int *drawLoc)
- {
- /* calculates top and bottom line IDs to be drawn in the rectangle. theText must
- be valid, and theRect is assumed to be in local window coordinates, which must
- be current port. The handles corresponding to these lines are returned */
-
- int height,p,h;
- int topID,botID,hTab;
-
- height = (*theText)->lineHeight;
- hTab = GetTabBarHeight(theText);
- p = (theRect->top - (thePort->portRect.top + hTab + 2))/height;
- h = theRect->bottom - theRect->top;
- *drawLoc = ((p+1) * height + hTab + 2) - (*theText)->descent;
- topID = p + (*theText)->topLine;
- botID = topID + (h/height);
- *top = GetLinkHandle(GetListHead(theText),topID);
- *bottom = GetLinkHandle(GetListHead(theText),botID);
- }
-
-
- int GetMarginOffset(textEdHdl theEdRec)
- {
- /* returns horizontal drawing origin for record */
- int margin;
-
- margin = ((GetCtlMin((*theEdRec)->hScroll) -
- GetCtlValue((*theEdRec)->hScroll)) *
- (*theEdRec)->mSpace) + 10;
-
- return(margin);
- }
-
-
- DrawList(WindowPtr theWindow,RgnHandle refreshRgn)
- {
- /* scans list, drawing text into theWindow. Ports settings for lineheight etc are
- used to space lines etc. If refreshRgn is not NIL, then the bounding box is
- used to calculate the bare minimum to update- this improves speed & efficiency */
-
- int lineHeight,margin,linePos,hLine;
- lineHdl topLine,botLine,hiliteLine;
- GrafPtr savePort;
- textEdHdl theEdRec;
- Rect refresh;
- TEHandle teText;
-
- if (IsEditKind(theWindow)) {
- GetPort(&savePort);
- SetPort(theWindow);
- if (refreshRgn != NIL)
- refresh = (*refreshRgn)->rgnBBox;
- else
- GetClipRect(theWindow,&refresh);
-
- theEdRec = GetWEditRecord(theWindow);
- if (theEdRec != NIL) {
- hLine = (*theEdRec)->hiliteLine;
- if (hLine > 0)
- hiliteLine = GetLinkHandle(GetListHead(theEdRec),hLine);
- CalcLinesToDraw(theEdRec,&refresh,&topLine,&botLine,&linePos);
- margin = GetMarginOffset(theEdRec);
- lineHeight = (*theEdRec)->lineHeight;
-
- while(topLine!=NIL) {
- MoveTo(margin,linePos);
- if (topLine == hiliteLine)
- ShowSelectedLine(linePos,lineHeight,(*theEdRec)->descent);
- HLock((Handle) topLine);
- /*DrawText(&(*topLine)->theLine,1,(*topLine)->theLine[0]);*/
- DrawTabText(&(*topLine)->theLine,theEdRec,margin,linePos);
- HUnlock((Handle) topLine);
- TextMode(srcOr);
- linePos += lineHeight;
- if (topLine==botLine)
- break;
-
- topLine = (*topLine)->nextLine;
- }
- }
- SetPort(savePort);
- }
- }
-
-
- ShowSelectedLine(int lineBase,int lineHeight,int descent)
- {
- /* inverts given line in window */
- Rect LRect;
-
- /*BitClr(&HiliteMode,pHiliteBit);*/
- SetRect(&LRect,0,lineBase-lineHeight+descent,640,lineBase+descent);
- PaintRect(&LRect);
- TextMode(patBic);
- }
-
-
- DrawTabText(char* lineStart,textEdHdl theText,int margin,int lineBase)
- {
- /* given a pointer to the first location of an AAG format line in memory, this
- function draws it to the screen in sections, positioning it at the tab locations
- given in the tab record of theText. */
-
- Byte sectionLength,tabIndex;
- Byte tLength,cCount;
- int mSpc,tabLoc,tabChar;
-
- cCount = 0;
- tabIndex = 0;
- tLength = *lineStart;
- mSpc = (*theText)->mSpace;
- lineStart++; /* point to first section count */
- do {
- sectionLength = *lineStart; /* get count of characters in section */
-
- if (sectionLength > 0) /* if non-zero...*/
- DrawText(lineStart,1,sectionLength); /* draw it */
-
- lineStart += sectionLength+1; /* skip to next section*/
- cCount += sectionLength+1; /* count up how many so far */
- do {
- tabIndex++;
- tabChar = (*theText)->tabs[tabIndex]; /* get next tab location */
- if (tabChar != 0)
- tabLoc = margin + (tabChar * mSpc); /* calculate pixel offset */
- else
- tabLoc = thePort->pnLoc.h+mSpc;
- }
- while (thePort->pnLoc.h > tabLoc);
- MoveTo(tabLoc,lineBase); /* draw from tab position */
- }
- while (cCount < tLength);
- }
-
-
- LoadText(SFReply *theReply,WindowPtr theWindow)
- {
- /* loads file specified in FS reply record into memory & converts it to link struct */
-
- Handle temp;
- OSErr theErr;
- long byteCount;
- int pathRef;
- GrafPtr savePort;
- textEdHdl theEdRec;
-
- if(theReply->good && IsEditKind(theWindow)) {
- theErr = FSOpen(&theReply->fName,theReply->vRefNum,&pathRef);
- if (theErr == noErr) {
- theErr = GetEOF(pathRef,&byteCount);
-
- temp = NewHandle(byteCount);
-
- if (temp != NIL) {
- HLock(temp);
- theErr = FSRead(pathRef,&byteCount,*temp);
- HUnlock(temp);
-
- SetWTitle(theWindow,&theReply->fName);
- BuildTList(temp,theWindow);
- DisposHandle(temp);
-
- theEdRec = GetWEditRecord(theWindow);
- if (theEdRec != NIL)
- (*theEdRec)->asmFile = *theReply;
- }
- else
- SysBeep(1);
-
- theErr = FSClose(pathRef);
- GetPort(&savePort);
- SetPort(theWindow);
- EraseRect(&thePort->portRect);
- InvalRect(&thePort->portRect);
- SetPort(savePort);
- }
- }
- }
-
-
- BuildTList(Handle theText,WindowPtr theEdWindow)
- {
- /* higher level call to TextToList using edit window parameter */
-
- long tLength;
- char *cPtr;
- textEdHdl theEdRec;
- lineHdl listTail,listHead;
-
- if (theText != NIL && IsEditKind(theEdWindow)) {
- theEdRec = GetWEditRecord(theEdWindow);
- if (theEdRec != NIL) {
- DisposeList(theEdRec);
- listTail = GetListTail(theEdRec);
- listHead = GetListHead(theEdRec);
- tLength = GetHandleSize(theText);
- HLock(theText);
- cPtr = *theText;
- TextToList(&listTail,&listHead,cPtr,tLength);
- HUnlock(theText);
- SetListTail(theEdRec,listTail);
- SetListHead(theEdRec,listHead);
- if (listHead != NIL)
- (*theEdRec)->curEdLin = 1;
- InitEdDisplay(theEdWindow);
- }
- }
- }
-
-
- DisposeList(textEdHdl theTextRec)
- {
- /* disposes of all links in theTextRec chain. This can be used prior to removing
- or reinitialising the edit record. Usually called for you by a higher level
- function. The head and tail fields are set to NIL at the end */
-
- lineHdl temp,disp;
-
- if (theTextRec != NIL) {
- temp = GetListHead(theTextRec);
-
- while (temp != NIL) {
- disp = temp;
- temp = (*temp)->nextLine;
- DisposHandle((Handle)disp);
- }
- SetListHead(theTextRec,NIL);
- SetListTail(theTextRec,NIL);
- }
- }
-
-
- DisposeEdRecord(textEdHdl theTextRec)
- {
- /* disposes of the linked list, then disposes of itself. The refcon field of the
- owner window is set to NIL, any other references to the record become invalid */
-
- TEHandle txt;
-
- if (theTextRec != NIL) {
- SetWRefCon((*theTextRec)->owner,0L);
- DisposeList(theTextRec);
- DisposHandle((Handle) theTextRec);
- }
- }
-
-
- int GetLineCharCount(textEdHdl theText,int lineID)
- {
- /* returns the number of characters in the given line. If line non-existant, returns
- zero */
-
- lineHdl theLink;
-
- if (theText != NIL) {
- theLink = GetListHead(theText);
- theLink = GetLinkHandle(theLink,lineID);
- if (theLink != NIL)
- return((*theLink)->theLine[0]);
- }
- return(0);
- }
-
-
- long GetNumberLines(textEdHdl theTextRec)
- {
- /* returns the number of lines in the edit record (by counting 'em!) */
-
- long t = 0;
- lineHdl temp;
-
- if (theTextRec != NIL) {
- temp = GetListHead(theTextRec);
-
- for (;temp != NIL;temp = (*temp)->nextLine,t++);
-
- }
- return(t);
- }
-
-
- int GetLineHeight(WindowPtr theWindow)
- {
- /* returns lineheight for given window's grafport */
-
- FontInfo theFInfo;
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort(theWindow);
- GetFontInfo(&theFInfo);
- SetPort(savePort);
- return(theFInfo.ascent + theFInfo.descent + theFInfo.leading);
- }
-
-
- int GetDescent(WindowPtr theWindow)
- {
- /* returns descent for given window's grafport */
-
- FontInfo theFInfo;
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort(theWindow);
- GetFontInfo(&theFInfo);
- SetPort(savePort);
- return(theFInfo.descent);
- }
-
-
- int GetMSpace(WindowPtr theWindow)
- {
- /* returns m space of window's font */
- GrafPtr savePort;
- int w;
-
- GetPort(&savePort);
- SetPort(theWindow);
- w = CharWidth('m');
- SetPort(savePort);
- return(w);
- }
-
-
- int GetLinesFit(WindowPtr theWindow)
- {
- /* calculates how many lines can fit in theWindow height and returns it */
-
- Rect r;
- int wHeight,lHeight;
- textEdHdl theText;
-
- if (IsEditKind(theWindow)) {
- theText = GetWEditRecord(theWindow);
- r = theWindow->portRect;
- lHeight = GetLineHeight(theWindow);
- wHeight = r.bottom - r.top - GetTabBarHeight(theText) - 17 - lHeight;
- return(wHeight/lHeight);
- }
- else
- return(0);
- }
-
-
- int GetHCharsFit(WindowPtr theWindow,int mSpace)
- {
- /* calculates how many characters can fit across theWindow and returns it */
-
- Rect r;
- int wWidth;
-
- if (IsEditKind(theWindow)) {
- r = theWindow->portRect;
- wWidth = r.right - r.left - 15;
- return(wWidth/mSpace);
- }
- else
- return(0);
- }
-
-
- InitEdDisplay(WindowPtr theWindow)
- {
- /* call when window first opened to initialise record to show top of file, set
- insertion point, etc Normally called for you after text loaded */
-
- textEdHdl theText;
- int edResult;
- ControlHandle vS,hS;
-
- if (IsEditKind(theWindow)) {
- theText = GetWEditRecord(theWindow);
- GetScrollBars(theWindow,&vS,&hS);
- SetCtlValue(vS,1);
- if (theText != NIL) {
- (*theText)->linesSelected = 0;
- (*theText)->endSelChar = 0;
- (*theText)->lineHeight = GetLineHeight(theWindow);
- (*theText)->descent = GetDescent(theWindow);
- (*theText)->mSpace = GetMSpace(theWindow);
- (*theText)->tabHeight = 0;
- ReCalcLineRange(theWindow);
- }
- }
- }
-
-
- long CalcSizeNeeded(textEdHdl theText)
- {
- /* calculates space required to hold a text file representation of the linked list structure.
- This is the sum of the handle sizes, less the link pointer sizes */
-
- long runTotal = 0;
- long thisOne;
- lineHdl theLink;
-
- if (theText != NIL) {
- theLink = GetListHead(theText);
-
- while (theLink != NIL) {
- thisOne = GetHandleSize(theLink) - (sizeof(lineHdl)*2);
- runTotal += thisOne;
- theLink = (*theLink)->nextLine;
- }
-
- return(runTotal);
- }
- return(NIL);
- }
-
-
- Handle MakeTextFile(textEdHdl theText)
- {
- /* given a handle to a linked text structure, a text file is generated from it, and the handle to
- this returned. This can then be saved as a text file on disk if required */
-
- long tfSize;
- Handle txtBlock = NIL;
- lineHdl tLink;
- Ptr s1,s2;
- int sLen;
-
- if (theText != NIL) {
- tfSize = CalcSizeNeeded(theText);
- if (tfSize > 0) {
- txtBlock = NewHandle(tfSize);
- if (txtBlock != NIL) {
- HLock(txtBlock);
- s2 = *txtBlock;
- tLink = GetListHead(theText);
-
- while (tLink != NIL) {
- HLock((Handle) tLink);
- s1 = &(*tLink)->theLine;
- sLen = *s1;
- s1++;
- BlockMove(s1,s2,sLen);
- HUnlock((Handle) tLink);
- s2 += sLen;
- *s2 = 0x0D;
- s2++;
- tLink = (*tLink)->nextLine;
- }
-
- HUnlock(txtBlock);
- }
- }
- }
- return(txtBlock);
- }
-
-
-
-
-